package com.example.wwww.repo;

import com.example.wwww.model.*;
import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Component
public class InMemoryStore {
    private final Map<Long, User> users = new ConcurrentHashMap<>();
    private final Map<Long, Dish> dishes = new ConcurrentHashMap<>();
    private final Map<Long, Order> orders = new ConcurrentHashMap<>();
    private final Map<Long, Merchant> merchants = new ConcurrentHashMap<>();
    private final Map<Long, RiderLocation> riderLocations = new ConcurrentHashMap<>();

    private final AtomicLong userId = new AtomicLong(3);
    private final AtomicLong dishId = new AtomicLong(6);
    private final AtomicLong orderId = new AtomicLong(1002);
    private final AtomicLong merchantId = new AtomicLong(2);
    private final AtomicLong riderLocationId = new AtomicLong(0);

    private static String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    @PostConstruct
    public void seed() {
        // Users
        User admin = new User();
        admin.setId(1L); admin.setUsername("admin"); admin.setPassword("1234");
        admin.setPhone("13800138000"); admin.setEmail("admin@test.com");
        admin.setType("user"); admin.setName("管理员"); admin.setAvatar("👤");
        admin.setRegisterTime(now());
        users.put(admin.getId(), admin);

        User merchantUser = new User();
        merchantUser.setId(2L); merchantUser.setUsername("merchant1"); merchantUser.setPassword("1234");
        merchantUser.setPhone("13800138001"); merchantUser.setEmail("merchant@test.com");
        merchantUser.setType("merchant"); merchantUser.setName("美味餐厅"); merchantUser.setAvatar("🏪");
        merchantUser.setRegisterTime(now());
        users.put(merchantUser.getId(), merchantUser);

        User rider = new User();
        rider.setId(3L); rider.setUsername("rider1"); rider.setPassword("1234");
        rider.setPhone("13800138002"); rider.setEmail("rider@test.com");
        rider.setType("rider"); rider.setName("张师傅"); rider.setAvatar("🏍️");
        rider.setRegisterTime(now());
        users.put(rider.getId(), rider);

        // Merchant
        Merchant m = new Merchant();
        m.setId(2L); m.setName("美味餐厅"); m.setType("川菜");
        m.setAddress("北京市朝阳区xxx街道123号"); m.setPhone("010-12345678");
        m.setDescription("正宗川菜，麻辣鲜香，传承经典");
        m.setImage("https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=400&h=300&fit=crop");
        m.setRating(4.8); m.setDeliveryTime("30分钟"); m.setDeliveryFee(5.0); m.setMinOrder(20.0);
        m.setOpenTime("09:00-22:00"); m.setIsOpen(true); m.setTags(Arrays.asList("川菜","麻辣","正宗"));
        m.setSales(1256); m.setCreateTime(now());
        merchants.put(m.getId(), m);

        // Dishes
        addDish(1L, 2L, "宫保鸡丁", 28.0, 32.0, "川菜",
            "经典川菜，鸡肉嫩滑，花生香脆，麻辣鲜香",
            "https://images.unsplash.com/photo-1563379091339-03246963d4d2?w=400&h=300&fit=crop",
            50, 15, Arrays.asList("辣","推荐","热销"), "鸡肉,花生,干辣椒,花椒,葱,姜,蒜", "花生", 4.7, 128);
        addDish(2L, 2L, "麻婆豆腐", 22.0, 26.0, "川菜",
            "嫩滑豆腐配麻辣调料，口感丰富",
            "https://images.unsplash.com/photo-1582878826629-29b7ad1cdc43?w=400&h=300&fit=crop",
            30, 12, Arrays.asList("辣","素食"), "豆腐,猪肉末,豆瓣酱,花椒,葱,姜", "大豆", 4.5, 89);
        addDish(3L, 2L, "回锅肉", 35.0, 40.0, "川菜",
            "肥瘦相间的五花肉，配青椒炒制",
            "https://images.unsplash.com/photo-1565299624946-b28f40a0ca4b?w=400&h=300&fit=crop",
            25, 18, Arrays.asList("辣","推荐"), "五花肉,青椒,豆瓣酱,甜面酱,葱,姜,蒜", "无", 4.6, 76);
        addDish(4L, 2L, "水煮鱼", 48.0, 55.0, "川菜",
            "鲜嫩鱼肉，麻辣汤底，配菜丰富",
            "https://images.unsplash.com/photo-1563379091339-03246963d4d2?w=400&h=300&fit=crop",
            20, 25, Arrays.asList("辣","热销"), "草鱼,豆芽,白菜,干辣椒,花椒,葱,姜", "鱼类", 4.8, 95);
        addDish(5L, 2L, "蒜蓉西兰花", 18.0, 20.0, "素菜",
            "清爽素菜，蒜香浓郁，营养丰富",
            "https://images.unsplash.com/photo-1512621776951-a57141f2eefd?w=400&h=300&fit=crop",
            40, 8, Arrays.asList("素食","健康"), "西兰花,大蒜,盐,鸡精", "无", 4.3, 45);
        addDish(6L, 2L, "蛋炒饭", 15.0, 18.0, "主食",
            "粒粒分明的米饭，配鸡蛋炒制",
            "https://images.unsplash.com/photo-1603133872878-684f208fb84b?w=400&h=300&fit=crop",
            60, 10, Arrays.asList("推荐","经济"), "米饭,鸡蛋,葱花,盐,生抽", "鸡蛋", 4.4, 112);

        // Orders
        Order o1 = new Order();
        o1.setId(1001L); o1.setUserId(1L); o1.setMerchantId(2L); o1.setRiderId(null);
        o1.setDishes(Arrays.asList(makeOrderDish(1L, "宫保鸡丁", 28.0, 1), makeOrderDish(6L, "蛋炒饭", 15.0, 1)));
        o1.setTotalPrice(43.0); o1.setDeliveryFee(5.0); o1.setFinalPrice(48.0);
        o1.setStatus("pending"); o1.setRiderStatus("available"); o1.setOrderTime(now());
        o1.setDeliveryAddress("北京市朝阳区xxx小区1号楼2单元301"); o1.setCustomerPhone("13800138000"); o1.setCustomerName("张三");
        o1.setNotes("请送到门口"); o1.setEstimatedTime(30);
        orders.put(o1.getId(), o1);

        Order o2 = new Order();
        o2.setId(1002L); o2.setUserId(1L); o2.setMerchantId(2L); o2.setRiderId(3L);
        o2.setDishes(Arrays.asList(makeOrderDish(2L, "麻婆豆腐", 22.0, 1), makeOrderDish(5L, "蒜蓉西兰花", 18.0, 1)));
        o2.setTotalPrice(40.0); o2.setDeliveryFee(5.0); o2.setFinalPrice(45.0);
        o2.setStatus("delivering"); o2.setRiderStatus("delivering");
        o2.setOrderTime(now()); o2.setDeliveryAddress("北京市朝阳区xxx小区2号楼1单元201");
        o2.setCustomerPhone("13800138000"); o2.setCustomerName("李四"); o2.setEstimatedTime(25); o2.setRiderName("张师傅");
        orders.put(o2.getId(), o2);
    }

    private void addDish(Long id, Long merchantId, String name, Double price, Double originalPrice, String category,
                         String description, String image, Integer stock, Integer cookingTime, List<String> tags,
                         String ingredients, String allergens, Double rating, Integer sales) {
        Dish d = new Dish();
        d.setId(id); d.setMerchantId(merchantId); d.setName(name); d.setPrice(price); d.setOriginalPrice(originalPrice);
        d.setCategory(category); d.setDescription(description); d.setImage(image); d.setStock(stock);
        d.setCookingTime(cookingTime); d.setTags(tags); d.setIngredients(ingredients); d.setAllergens(allergens);
        d.setRating(rating); d.setSales(sales); d.setStatus("available"); d.setCreateTime(now());
        dishes.put(id, d);
    }

    private Order.OrderDish makeOrderDish(Long id, String name, Double price, Integer qty) {
        Order.OrderDish od = new Order.OrderDish();
        od.setId(id); od.setName(name); od.setPrice(price); od.setQuantity(qty);
        return od;
    }

    // Users
    public List<User> getUsers() { return new ArrayList<>(users.values()); }
    public Optional<User> getUserById(Long id) { return Optional.ofNullable(users.get(id)); }
    public Optional<User> getUserByUsername(String username) { return users.values().stream().filter(u -> username.equals(u.getUsername())).findFirst(); }
    public User addUser(User user) {
        long id = userId.incrementAndGet();
        user.setId(id); user.setRegisterTime(now());
        users.put(id, user); return user;
    }
    public User updateUser(Long id, User updates) {
        User existing = users.get(id); if (existing == null) return null;
        if (updates.getUsername() != null) existing.setUsername(updates.getUsername());
        if (updates.getPassword() != null) existing.setPassword(updates.getPassword());
        if (updates.getPhone() != null) existing.setPhone(updates.getPhone());
        if (updates.getEmail() != null) existing.setEmail(updates.getEmail());
        if (updates.getType() != null) existing.setType(updates.getType());
        if (updates.getName() != null) existing.setName(updates.getName());
        if (updates.getAvatar() != null) existing.setAvatar(updates.getAvatar());
        return existing;
    }

    // Dishes
    public List<Dish> getDishes() { return new ArrayList<>(dishes.values()); }
    public List<Dish> getDishesByMerchant(Long merchantId) {
        return dishes.values().stream().filter(d -> Objects.equals(d.getMerchantId(), merchantId)).collect(Collectors.toList());
    }
    public Optional<Dish> getDishById(Long id) { return Optional.ofNullable(dishes.get(id)); }
    public Dish addDish(Dish dish) {
        long id = dishId.incrementAndGet(); dish.setId(id); dish.setCreateTime(now());
        if (dish.getStatus() == null) dish.setStatus("available");
        dishes.put(id, dish); return dish;
    }
    public Dish updateDish(Long id, Dish updates) {
        Dish d = dishes.get(id); if (d == null) return null;
        if (updates.getName() != null) d.setName(updates.getName());
        if (updates.getPrice() != null) d.setPrice(updates.getPrice());
        if (updates.getOriginalPrice() != null) d.setOriginalPrice(updates.getOriginalPrice());
        if (updates.getCategory() != null) d.setCategory(updates.getCategory());
        if (updates.getDescription() != null) d.setDescription(updates.getDescription());
        if (updates.getImage() != null) d.setImage(updates.getImage());
        if (updates.getStock() != null) d.setStock(updates.getStock());
        if (updates.getCookingTime() != null) d.setCookingTime(updates.getCookingTime());
        if (updates.getTags() != null) d.setTags(updates.getTags());
        if (updates.getIngredients() != null) d.setIngredients(updates.getIngredients());
        if (updates.getAllergens() != null) d.setAllergens(updates.getAllergens());
        if (updates.getRating() != null) d.setRating(updates.getRating());
        if (updates.getSales() != null) d.setSales(updates.getSales());
        if (updates.getStatus() != null) d.setStatus(updates.getStatus());
        return d;
    }
    public boolean deleteDish(Long id) { return dishes.remove(id) != null; }

    // Orders
    public List<Order> getOrders() { return new ArrayList<>(orders.values()); }
    public List<Order> getOrdersByUser(Long userId) {
        return orders.values().stream().filter(o -> Objects.equals(o.getUserId(), userId)).collect(Collectors.toList());
    }
    public List<Order> getOrdersByMerchant(Long merchantId) {
        return orders.values().stream().filter(o -> Objects.equals(o.getMerchantId(), merchantId)).collect(Collectors.toList());
    }
    public List<Order> getOrdersByRider(Long riderId) {
        return orders.values().stream().filter(o -> Objects.equals(o.getRiderId(), riderId)).collect(Collectors.toList());
    }
    public List<Order> getAvailableOrders() {
        return orders.values().stream().filter(o -> Objects.equals(o.getRiderStatus(), "available")).collect(Collectors.toList());
    }
    public Optional<Order> getOrderById(Long id) { return Optional.ofNullable(orders.get(id)); }
    public Order addOrder(Order order) {
        long id = orderId.incrementAndGet(); order.setId(id); order.setOrderTime(now());
        if (order.getStatus() == null) order.setStatus("pending");
        if (order.getRiderStatus() == null) order.setRiderStatus("available");
        orders.put(id, order); return order;
    }
    public Order updateOrder(Long id, Order updates) {
        Order o = orders.get(id); if (o == null) return null;
        if (updates.getStatus() != null) o.setStatus(updates.getStatus());
        if (updates.getRiderStatus() != null) o.setRiderStatus(updates.getRiderStatus());
        if (updates.getRiderId() != null) o.setRiderId(updates.getRiderId());
        if (updates.getEstimatedTime() != null) o.setEstimatedTime(updates.getEstimatedTime());
        return o;
    }

    // Merchants
    public List<Merchant> getMerchants() { return new ArrayList<>(merchants.values()); }
    public Optional<Merchant> getMerchantById(Long id) { return Optional.ofNullable(merchants.get(id)); }

    // Rider locations
    public List<RiderLocation> getRiderLocations() { return new ArrayList<>(riderLocations.values()); }
    public List<RiderLocation> getActiveRiderLocations() {
        // Simplified: return all for demo
        return getRiderLocations();
    }
    public RiderLocation addRiderLocation(RiderLocation data) {
        long id = riderLocationId.incrementAndGet(); data.setId(id);
        if (data.getTimestamp() == null) data.setTimestamp(java.time.Instant.now().toString());
        riderLocations.put(id, data); return data;
    }
}


